#pragma once
#include<iostream>
#include<functional>
#include<string>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
#include<signal.h>
#include<unordered_map>
#include"Protocol.hpp"  

namespace server
{
    enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR,
        ACCEPT_ERR
    };

    // req是输入型参数，resp是输出型参数！

    //保证解耦
  

    const static int gbacklog = 2;
    const static uint16_t gport = 8080;
    using func_t = std::function<void(const HttpRequest &, HttpResponse &)>;

    class httpServer
    {
    public:
        httpServer(func_t func,const uint16_t &port = gport)
            : port_(port), listensock_(-1),func_(func)
        {
        }

        void initServer()
        {
            //1.首先就是要创建套接字
            //1.1创建一个套接字！
            listensock_ = socket(AF_INET,SOCK_STREAM,0);
            if(listensock_ == -1)
            {
                exit(SOCKET_ERR);
            }

            //设置地址复用！
            int opt = 1;
            setsockopt(listensock_,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

            //1.2进行绑定！
            struct sockaddr_in peer;
            bzero(&peer,sizeof(peer));
            peer.sin_family = AF_INET;
            peer.sin_addr.s_addr = INADDR_ANY;
            peer.sin_port = htons(port_);



            int n = bind(listensock_,(struct sockaddr*)&peer,sizeof(peer));

            if(n == -1)
            {
                printf("bind error\n");
                exit(BIND_ERR);
            }

            //3.设置socket 为监听状态！
           if (listen(listensock_, gbacklog) <  0)
           {
               exit(LISTEN_ERR);
           }
        
        }

        void start()
        {

            for (;;)
            {
                // signal(SIGCHLD, SIG_IGN); // 直接忽略子进程信号,那么操作系统就会自动回收

                // struct sockaddr_in peer;
                // socklen_t len = sizeof(peer);
                // int sock = accept(listensock_, (struct sockaddr *)&peer, &len);

                // std::cout << sock << std::endl;
                // if (sock == -1)
                // {
                //     continue; 
                // }

                // pid_t id = fork();
                // if (id == 0)
                // {
                //     close(listensock_);

                //     HandlerHttp(sock);
                //     close(sock);
                //     exit(0);
                // }
                // close(sock);
                sleep(1);

            }
        }

        ~httpServer()
        {
        }

    private:

        void HandlerHttp(int sock)
        {
            // while(1)
            // {
            //     sleep(1);
            // }
            
            // char buffer[1024];
            // ssize_t n = recv(sock,buffer,sizeof(buffer)-1,0);
            // HttpRequest req;
            // HttpResponse resp;
            // if(n>0)
            // {
            //     buffer[n] = 0;
            //     req.inbuffer = buffer;
            //     req.parse();
            //     func_(req,resp);
             
            //     send(sock,resp.outbuffer.c_str(),resp.outbuffer.size(),0);
            // }
            char buffer[1024];
            recv(sock,buffer,sizeof(buffer),0);
        }

    private:
        int listensock_; // tcp服务端也是要有自己的socket的！这个套接字的作用不是用于通信的！而是用于监听连接的！
        uint16_t port_;//tcp服务器的端口
        func_t func_;
        // std::unordered_map<std::string,func_t> funcs;

    };


}
